iT邦幫忙

2025 iThome 鐵人賽

DAY 8
0
佛心分享-SideProject30

Vibe Code與context engineering來打造個人專屬夥伴系列 第 8

第八日:從文件走向程式,Provisioning 工地正式開張

  • 分享至 

  • xImage
  •  

第八日:從文件走向程式,Provisioning 工地正式開張 🚧

昨天還在紙上談兵,今天終於把藍圖變成鋼筋水泥。第八天,我跟 Codex 不再只是畫圖、寫文件,而是真正下場「寫程式 + 跑測試」。整個工地總算開始冒煙了。以下是今天完整的紀錄。


一、今日戰場回顧:從文件到程式碼

昨天,我們已經把需求文件、API 契約、資料模型都寫好,算是蓋了一間樣品屋。今天的任務,就是把這些樣品拆掉,蓋一個真的能通電、能跑測試的Code。

根據今天的開發日誌,主要做了五件事:

  1. 建立 Go 模組與目錄結構,包含 service、HTTP handler、記憶體儲存層。
  2. 定義 US-001 的資料流:payload → notification key profile → destination grants → delivery token。
  3. 撰寫單元測試,涵蓋成功案例、idempotency、驗證失敗、quota 超標、目的地錯誤。
  4. 本地跑 go test ./...,全部測試通過 🎉。
  5. 寫好 curl 範例,直接打 API,驗證成功案例與錯誤案例。

一句話總結:今天不是「我覺得可以跑」,而是「真的能跑」。


二、程式碼工地巡禮

1. 記憶體儲存層 MemoryStore

一開始先有一個臨時倉庫,名字叫 MemoryStore。它就像工地的臨時鐵皮屋,雖然簡陋,但能放下所有工地器材。

  • 功能包括:儲存 payload、profiles、provisioning 結果、destination catalog、grants、audit log、delivery token。
  • 提供驗證目的地是否存在、是否 active。
  • 支援快照,讓測試時能直接抓目前 catalog 與 profiles 狀態。

關鍵設計:用 compositeKey(externalSystemID, approvalID) 當唯一索引,確保 idempotency。這保證「同樣的審核單重複送」不會創造兩份結果。

2. Service 層 Provisioner

然後是整個工地的施工主管 —— Provisioner。它負責 orchestrate 流程:

  1. 驗證輸入(缺欄位、email 格式錯誤、quota 超標、沒有目的地,全都會被攔下)。
  2. 確認 idempotency(如果同一個 approval_id 已經成功過,就直接回傳舊結果,並打上 Existing=true)。
  3. 儲存 payload。
  4. 驗證 destinations 是否存在於 catalog。
  5. 生成一堆 identifier(notification key、API key、delivery token、audit trace)。
  6. 儲存 profile 與 destination grants。
  7. 儲存 delivery token。
  8. Persist 結果,並寫入 audit trail。

整個 Provisioner 就像是「現場監工」,一條龍服務。

3. HTTP Handler

接下來就是讓外部能打 API 的 HTTP handler。

  • Endpoint: POST /internal/v1/provisioning/notification-keys
  • 驗證 JSON payload,不允許未知欄位。
  • Metadata 僅允許 string 或 number(若傳物件就直接 400)。
  • 呼叫 Provisioner,回傳結果(201 Created)。
  • 針對錯誤類型,回傳對應 HTTP 狀態:
    • Invalid request → 400
    • Quota 超標 → 422
    • Destination not found → 422
    • 其他錯誤 → 500

這讓 API 用起來更「雲原生感」,而不是只有一個「500,自己看 log」。

4. Domain Model

model.go,定義了所有核心結構:

  • ProvisionRequest:API payload。
  • ProvisionResult:API 回傳結果。
  • NotificationKeyProfile:API key profile。
  • DestinationRequest / DestinationGrant:目的地相關。
  • QuotaConfig:流量管制。

這些結構就像是整個專案的「混凝土」。沒有它們,整個工地就會倒。

5. Main 啟動程式

最後是 main.go,啟動一個 HTTP server,掛上 handler。並支援環境變數設定 PROVISIONING_MAX_REQUESTS_PER_MINUTE,可以動態調整限流。

這個 server 現在可以本地跑起來,對外回應 201 或 422,算是進入「能 demo」的階段。


三、單元測試:給工地戴安全帽

光蓋工地還不夠,還要檢查每個工人有沒有戴安全帽。

今天加了完整的單元測試:

  1. 成功案例:正確的 payload → 201 Created,且回傳正確的 notification key 與目的地授權。
  2. Idempotency:同一個 request 重送,應該重用舊的 notification key,並打上 Existing=true
  3. Invalid Request:缺欄位或 email 格式錯誤 → 400。
  4. Quota Exceeded:超過平台 policy → 422。
  5. Destination Validation Error:destination 不存在或 inactive → 422。
  6. Invalid Metadata:metadata 傳 nested object → 400。

全部測試通過,這讓我心裡更安心,不怕 demo 的時候爆炸。


四、curl 實測:工地通電啦

最後一步是「通電驗收」。今天寫了 curl 測試案例:

  1. 成功案例:正確 payload → 回傳一組 notification key、delivery token。
  2. 錯誤案例:缺少目的地 → 422,提示 DESTINATION_NOT_FOUND

測完之後,我才敢宣告:工地真的能運轉


五、今日心得:AI 共筆 = 加速器,但不是萬能

今天最大的體會:AI 不只是幫忙寫文件,它也能幫忙寫程式碼,甚至測試。但它的角色比較像「加速器」,而不是「取代工程師」。

舉幾個例子:

  • AI 的速度:一開始我只丟需求,它很快就幫我生出 HTTP handler skeleton,少打了兩百行樣板程式碼。
  • AI 的盲點:它會寫一些「過於完美」的 code,例如錯誤處理直接用 500,沒有考慮 domain-specific 狀況。我需要自己補上。
  • AI 的好用之處:幫忙生成測試,尤其是 payload JSON,手動寫很累,它三秒鐘就搞定。

總結:AI 幫忙省下 50% 的樣板時間,但設計、邏輯、驗證還是得自己來。


六、明日計畫:從 Prototype 到 Platform

今天的工地已經「能跑」。明天的方向:

  1. 補真實儲存層:不再只用 MemoryStore,要改用 DB。
  2. 補發 API:delivery token 過期,要有 re-issue 機制。
  3. Destination Catalog 同步策略:目前是 seed,未來要跟 Teams 動態同步。
  4. 更完整的測試:增加 integration test,模擬實際 HTTP call。

一句話:從「能跑」走向「能用」。


七、結語:從文件藍圖到工地煙火

第八天,我終於能驕傲地說:我們有一個能運作的 Provisioning API prototype

  • 文件 → 程式碼 → 測試 → 驗收,全都跑完一輪。
  • 雖然還是 MemoryStore,但至少不再只是紙上建築。
  • AI 在過程中給了極大助力,讓我更快到達這一步。

未來還有很多挑戰,但今天,這間工地終於開張、點燈、能 demo。
這就是鐵人賽 Day 8 的最大收穫。

👉 明天再戰,繼續搬磚! 🚀



上一篇
第七日:與 Codex 共筆的一天,需求從草圖到工地藍圖
系列文
Vibe Code與context engineering來打造個人專屬夥伴8
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言